/** \file    auto_aptr.h
  * \brief   YATL::auto_aptr behaves like std::auto_aptr but suitable for pointers on arrays,
  *			 because it calls delete[] on destruction
  * \date    2001, 2002
  * \author  Fedor Chelnokov
  * \version $Header: /home/cscom1r4/cvsroot/cs/include/xtd/auto_aptr.h,v 1.1 2004/12/02 23:53:11 cscom1r4 Exp $
  */

#ifndef _auto_aptr_h_
#define _auto_aptr_h_

#ifndef _THROW0
#define _THROW0()
#endif

//std::auto_ptr from VS6 bundle has leak of 'reset' member function, update it:
//	void reset(T *__px=0) {
//		if (__px != _Ptr) 
//			*this = auto_ptr<T>(__px);
//	}

namespace xtd
{

template<class T>
	class auto_aptr {
public:
	typedef T elementTpe;
	explicit auto_aptr(T *p = 0) _THROW0()
		: _own(p != 0), _ptr(p) {}
	explicit auto_aptr(unsigned n)
		: _own(true), _ptr(new T[n]) {}
	auto_aptr(const auto_aptr<T>& y) _THROW0()
		: _own(y._own), _ptr(y.release()) {}
	auto_aptr<T>& operator=(const auto_aptr<T>& y) _THROW0()
		{if (this != &y)
			{if (_ptr != y.get())
				{if (_own)
					delete[] _ptr;
				_own = y._own; }
			else if (y._own)
				_own = true;
			_ptr = y.release(); }
		return (*this); }
	~auto_aptr()
		{if (_own)
			delete[] _ptr; }
	T& operator*() const _THROW0()
		{return (*get()); }
	T& operator[]( int n ) _THROW0()
		{return (get()[n]); }
	const T& operator[]( int n ) const _THROW0()
		{return (get()[n]); }
#ifdef _MSC_VER
#pragma warning( push )
#pragma warning( disable : 4284 )
#endif
	T *operator->() const _THROW0()
		{return (get()); }
#ifdef _MSC_VER
#pragma warning( pop )
#endif
	T *get() const _THROW0()
		{return (_ptr); }
	T *release() const _THROW0()
		{((auto_aptr<T> *)this)->_own = false;
		return (_ptr); }
	void reset(T *__px=0) {
		if (__px != _ptr) 
			*this = auto_aptr<T>(__px);
	}
private:
	bool _own;
	T *_ptr;
	};

} // namespace xtd

#endif //_auto_aptr_h_
